#ifndef __POPUP_LOGGER_UI_HPP__
#define __POPUP_LOGGER_UI_HPP__

#include <string>
#include <stdarg.h>

namespace PopupUtils
{
  typedef enum {
    POPUP_LOG_TRACE,
    POPUP_LOG_INFO,
    POPUP_LOG_WARNING,
    POPUP_LOG_ERROR,
    POPUP_LOG_CRITICAL
  } LogLevel;

  const char *convertLogLevelToString(LogLevel p_level);

  void trace(const char *format, ...);
  void trace(const std::string & p_msg);
  void info(const char *format, ...);
  void info(const std::string & p_msg);
  void warning(const char *format, ...);
  void warning(const std::string & p_msg);
  void error(const char *format, ...);
  void error(const std::string & p_msg);
  void critical(const char *format, ...);
  void critical(const std::string & p_msg);

  struct LoggerUI
  {
    virtual ~LoggerUI() {}

  protected:
    virtual void logmsg(LogLevel p_level,
                         const char *format,
                         va_list p_args) = 0;

    static void init(LoggerUI * p_logger) {
      staticLogger = p_logger;
    }
    static inline LoggerUI *instance() {
      return staticLogger;
    }

  private:
    static LoggerUI *staticLogger;

    friend void trace(const char *format, ...);
    friend void trace(const std::string & p_msg);
    friend void info(const char *format, ...);
    friend void info(const std::string & p_msg);
    friend void warning(const char *format, ...);
    friend void warning(const std::string & p_msg);
    friend void error(const char *format, ...);
    friend void error(const std::string & p_msg);
    friend void critical(const char *format, ...);
    friend void critical(const std::string & p_msg);
  };

  struct DefaultLogger : public LoggerUI
  {
    ~DefaultLogger() {};

    //!
    //! Appends a log message
    //!
    //! \param[in] p_log     Message to log
    //! \param[in] p_level   Log level of the message
    //!
    void logmsg(LogLevel p_level, const char *format, va_list p_args);
  };
}

#endif

